package zdream.pmfield.stage.buff.ailment;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import zdream.pmfield.data.foe.MoveAdditionalEffects;
import zdream.pmfield.data.foe.VStat;
import zdream.pmfield.stage.buff.foe.FoeStageBuff;
import zdream.pmfield.stage.director.AttackContext;
import zdream.pmfield.stage.director.Roll;
import zdream.pmfield.stage.director.HookType;
import zdream.pmfield.stage.director.Hooks;
import zdream.pmfield.stage.object.FoeActor;

/**
 * <p>麻痹状态, 不过这个和 Pokemon 里面的不一样, 参考 For The King 的效果.
 * <p>在 {@link Roll} 判定时, 第一个骰子必定失败.
 * 该 {@link FoeActor} 麻痹 3 回合 (不是 3 轮) 之后,
 * 后续通过 {@link zdream.pmfield.data.foe.VStat#LUCK} 来决定是否恢复.
 * </p>
 *
 * @author Zdream
 * @date 2023-11-21
 * @since 0.0.1
 */
public class ParalysisBuff extends FoeStageBuff {
	public static final String CATEGORY = MoveAdditionalEffects.E_PARALYSIS;
	public final BuffSpan span;
	private final Set<String> allowedRollTitles = new HashSet<>(Arrays.asList(
			DrowsyBuff.CATEGORY
	));

	public ParalysisBuff(FoeActor foe) {
		super(foe);
		span = new DurationBuffSpan()
				.withMinDuration(3)
				.withStartTime(now());
	}

	@Override
	public String getCategory() {
		return CATEGORY;
	}

	@Override
	public String toString() {
		return "麻痹";
	}

	@Override
	public void init() {
		preventSameBuffBeforeFoeReceiveBuff();
		onHook(HookType.BEFORE_ATTACK_ROLL_CHECK)
				.handle(this::beforeRollCheck)
				.withPriority(-1000)
				.buildAndSave();
		onHook(HookType.DURING_ROLL_CHECK)
				.handle(this::duringRollCheck)
				.withPriority(-1000)
				.buildAndSave();
		onHook(HookType.BEFORE_FOE_TURN_START)
				.handle(span::checkIsNeedCured)
				.buildAndSave();
	}

	/**
	 * 如果没有投入专注点, 第一个判定必定失败
	 */
	public void beforeRollCheck(Hooks.HookContext rawContext) {
		Hooks.AttackHookContext castContext = rawContext.as();
		AttackContext context = castContext.attackContext;
		if (context.attacker != target) {
			return;
		}

		final Roll[] rolls = context.rolls;

		if (rolls.length < 1) {
			return;
		}

		// 如果有专注, 则跳过
		if (rolls[0].focus) {
			return;
		}

		rolls[0].affectedBy = this;
		rolls[0].affectResult = false;
	}

	/**
	 * 只判定第一个骰子.
	 * 如果不是 {@link zdream.pmfield.data.foe.VStat#LUCK}, 且没有投入专注点, 判定必定失败.
	 */
	public void duringRollCheck(Hooks.HookContext rawContext) {
		Hooks.RollCheckHookContext context = rawContext.as();

		if (!allowedRollTitles.contains(context.title)) {
			return;
		}

		final Roll[] rolls = context.rolls;
		if (rolls.length < 1) {
			return;
		}

		// 如果有专注, 则跳过
		if (rolls[0].focus || rolls[0].vStat == VStat.LUCK) {
			return;
		}

		rolls[0].affectedBy = this;
		rolls[0].affectResult = false;
	}
}
